" Copyright 2011 The Go Authors. All rights reserved.
" Use of this source code is governed by a BSD-style
" license that can be found in the LICENSE file.
"
" Check out the docs for more information at /doc/vim-go.txt
"
function! go#import#SwitchImport(enabled, localname, path, bang)
    let view = winsaveview()
    let path = substitute(a:path, '^\s*\(.\{-}\)\s*$', '\1', '')

    " Quotes are not necessary, so remove them if provided.
    if path[0] == '"'
        let path = strpart(path, 1)
    endif
    if path[len(path)-1] == '"'
        let path = strpart(path, 0, len(path) - 1)
    endif

    " if given a trailing slash, eg. `github.com/user/pkg/`, remove it
    if path[len(path)-1] == '/'
        let path = strpart(path, 0, len(path) - 1)
    endif

    if path == ''
        call s:Error('Import path not provided')
        return
    endif

    if a:bang == "!"
        let out = system("go get -u -v ".shellescape(path))
        if v:shell_error
            call s:Error("Can't find import: " . path . ":" . out)
        endif
    endif
    let exists = go#tool#Exists(path)
    if exists == -1
        call s:Error("Can't find import: " . path)
        return
    endif

    " Extract any site prefix (e.g. github.com/).
    " If other imports with the same prefix are grouped separately,
    " we will add this new import with them.
    " Only up to and including the first slash is used.
    let siteprefix = matchstr(path, "^[^/]*/")

    let qpath = '"' . path . '"'
    if a:localname != ''
        let qlocalpath = a:localname . ' ' . qpath
    else
        let qlocalpath = qpath
    endif
    let indentstr = 0
    let packageline = -1 " Position of package name statement
    let appendline = -1  " Position to introduce new import
    let deleteline = -1  " Position of line with existing import
    let linesdelta = 0   " Lines added/removed

    " Find proper place to add/remove import.
    let line = 0
    while line <= line('$')
        let linestr = getline(line)

        if linestr =~# '^package\s'
            let packageline = line
            let appendline = line

        elseif linestr =~# '^import\s\+('
            let appendstr = qlocalpath
            let indentstr = 1
            let appendline = line
            let firstblank = -1
            let lastprefix = ""
            while line <= line("$")
                let line = line + 1
                let linestr = getline(line)
                let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)')
                if empty(m)
                    if siteprefix == "" && a:enabled
                        " must be in the first group
                        break
                    endif
                    " record this position, but keep looking
                    if firstblank < 0
                        let firstblank = line
                    endif
                    continue
                endif
                if m[1] == ')'
                    " if there's no match, add it to the first group
                    if appendline < 0 && firstblank >= 0
                        let appendline = firstblank
                    endif
                    break
                endif
                let lastprefix = matchstr(m[4], "^[^/]*/")
                if a:localname != '' && m[3] != ''
                    let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath)
                endif
                let appendstr = m[2] . qlocalpath
                let indentstr = 0
                if m[4] == path
                    let appendline = -1
                    let deleteline = line
                    break
                elseif m[4] < path
                    " don't set candidate position if we have a site prefix,
                    " we've passed a blank line, and this doesn't share the same
                    " site prefix.
                    if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0
                        let appendline = line
                    endif
                elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0
                    " first entry of site group
                    let appendline = line - 1
                    break
                endif
            endwhile
            break

        elseif linestr =~# '^import '
            if appendline == packageline
                let appendstr = 'import ' . qlocalpath
                let appendline = line - 1
            endif
            let m = matchlist(linestr, '^import\(\s\+\)\(\S*\s*\)"\(.\+\)"')
            if !empty(m)
                if m[3] == path
                    let appendline = -1
                    let deleteline = line
                    break
                endif
                if m[3] < path
                    let appendline = line
                endif
                if a:localname != '' && m[2] != ''
                    let qlocalpath = printf("%s %" . len(m[2])-1 . "s", a:localname, qpath)
                endif
                let appendstr = 'import' . m[1] . qlocalpath
            endif

        elseif linestr =~# '^\(var\|const\|type\|func\)\>'
            break

        endif
        let line = line + 1
    endwhile

    " Append or remove the package import, as requested.
    if a:enabled
        if deleteline != -1
            call s:Error(qpath . ' already being imported')
        elseif appendline == -1
            call s:Error('No package line found')
        else
            if appendline == packageline
                call append(appendline + 0, '')
                call append(appendline + 1, 'import (')
                call append(appendline + 2, ')')
                let appendline += 2
                let linesdelta += 3
                let appendstr = qlocalpath
                let indentstr = 1
            endif
            call append(appendline, appendstr)
            execute appendline + 1
            if indentstr
                execute 'normal >>'
            endif
            let linesdelta += 1
        endif
    else
        if deleteline == -1
            call s:Error(qpath . ' not being imported')
        else
            execute deleteline . 'd'
            let linesdelta -= 1

            if getline(deleteline-1) =~# '^import\s\+(' && getline(deleteline) =~# '^)'
                " Delete empty import block
                let deleteline -= 1
                execute deleteline . "d"
                execute deleteline . "d"
                let linesdelta -= 2
            endif

            if getline(deleteline) == '' && getline(deleteline - 1) == ''
                " Delete spacing for removed line too.
                execute deleteline . "d"
                let linesdelta -= 1
            endif
        endif
    endif

    " Adjust view for any changes.
    let view.lnum += linesdelta
    let view.topline += linesdelta
    if view.topline < 0
        let view.topline = 0
    endif

    " Put buffer back where it was.
    call winrestview(view)

endfunction


function! s:Error(s)
    echohl Error | echo a:s | echohl None
endfunction


" vim:ts=4:sw=4:et
